﻿using Microsoft.VisualStudio.Modeling;
using System.Collections.Generic;
using Project.Co_DataTransformationPrototype;

namespace Project.Co_DataTransformationPrototype
{

    public static partial class EntityAssociationBuilder
    {
        internal static bool CanAcceptSource(ModelElement sourceElement)
        {
            bool blnAccepted = false;
            Entity element = sourceElement as Entity;

            if (element != null)
            {
                //if (element.ExampleAttributes.Exists(obj => obj.isPrimaryKey == true))
                    blnAccepted = true;
            }

            return blnAccepted;
        }

        internal static bool CanAcceptSourceAndTarget(ModelElement sourceElement, ModelElement targetElement)
        {
            return (targetElement is Entity || targetElement is EntityShape);
        }

        internal static void Connect(ModelElement sourceElement, ModelElement targetElement)
        {
            bool isValidSource = false;
            bool isValidTarget = false;
            EntityAttribute primaryAttribute = null;
            EntityAttribute foreignAttribute = null;
            Entity source = sourceElement as Entity;
            Entity target = targetElement as Entity;

            if (source != null)
            {
                // Set Source entity's attribute for this relationship
                primaryAttribute = source.EntityAttributes.Find(att => att.isPrimaryKey == true);

                if (primaryAttribute != null)
                {
                    isValidSource = true;

                    // Set Target entity
                    if (target == null)
                        target = (targetElement as EntityShape).ModelElement as Entity;

                    // Set Target entity's attribute for this relationship
                    if (target != null)
                        isValidTarget = setTargetForeignKeyAttribute(target, out foreignAttribute);
                }
            }

            if (isValidSource && isValidTarget)
            {
                // Define link
                ConnectorInfo linkInfo = new ConnectorInfo();
                linkInfo.target = target;
                linkInfo.source = source;
                linkInfo.nameAttributeInSource = primaryAttribute.Name;

                if (foreignAttribute == null)
                {
                    // Define foreignKey attribute
                    System.Guid newAttributeID;
                    AttributeInfo attrInfo = new AttributeInfo();
                    attrInfo.name = "FK_" + primaryAttribute.Name;
                    attrInfo.type = primaryAttribute.Type;
                    attrInfo.parentEntity = target;
                    attrInfo.referencedEntity = source.Id;

                    // Add attribute
                    Operators.Define(target.Store).CreateOperator<AttributeInfo>(new List<AttributeInfo> { attrInfo }, out newAttributeID);
                    foreignAttribute = target.Store.ElementDirectory.FindElement(newAttributeID) as EntityAttribute;
                }

                if (foreignAttribute != null && foreignAttribute.Type.Equals(primaryAttribute.Type))
                {
                    // Set attribute's isForeignKey value to true
                    Operators.Define(target.Store).UpdateAttributeProperty(EntityAttribute.isForeignKeyDomainPropertyId, foreignAttribute, true, source);
                    linkInfo.nameAttributeInTarget = foreignAttribute.CurrentName;

                    // Add link !
                    Operators.Define(target.Store).CreateOperator<ConnectorInfo>(new List<ConnectorInfo> { linkInfo });
                }
                else
                {
                    System.Windows.Forms.MessageBox.Show(string.Format("Referenced attribute '{0}.{1} (type:{2})' and referencing attribute '{3} (type:{4})' must have the same data type.", source.CurrentName, primaryAttribute.CurrentName, primaryAttribute.Type.ToString(), foreignAttribute.CurrentName, foreignAttribute.Type.ToString()), "Element Relationship - Warning", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
                }
            }
            else
            {
                if (!isValidSource)
                    System.Windows.Forms.MessageBox.Show(string.Format("{0} {1} must have a primary key attribute.", source.GetDomainClass().DisplayName, source.Name), "Element Relationship - Warning", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
                else if (!isValidTarget)
                    System.Windows.Forms.MessageBox.Show(string.Format("{0} {1} must define an existing attribute as a foreign-key attribute.", target.GetDomainClass().DisplayName, target.Name), "Element Relationship - Warning", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
            }
        }

        private static bool setTargetForeignKeyAttribute(Entity target, out EntityAttribute foreignAttribute)
        {
            EntityAttribute attribute = null;
            bool isValidTarget = false;

            if (target.EntityAttributes.Count == 0)
            {
                // We'll automatically create foreign key attribute based on source's primary key name
                isValidTarget = true; 
            }
            else
            {
                // We need to know the exact attribute which is to be set as foreign key
                UI.SelectAttributeForm dlgBox = new UI.SelectAttributeForm(target);
                System.Windows.Forms.DialogResult dlgResult = dlgBox.ShowDialog();

                if (dlgResult == System.Windows.Forms.DialogResult.OK)
                {
                    attribute = dlgBox.foreignKeyAttribute;
                    isValidTarget = true;
                }
            }
            foreignAttribute = attribute;

            return isValidTarget;
        }    

    }
}
